#include "myStdio.h"

FILE_* fopen_(const char* path_name, const char* mode)
{
    int flags = 0;// 文件标记位—打开方式
    int defaultMode = 0666;// 文件创建的默认权限
    if(strcmp(mode, "r") == 0)
    {
        // 只读
        flags |= O_RDONLY;
    }
    else if(strcmp(mode, "w") == 0)
    {
        // 只写
        flags |= (O_WRONLY | O_CREAT | O_TRUNC);
    }
    else if(strcmp(mode, "a") == 0)
    {
        // 追加
        flags |= (O_WRONLY | O_CREAT | O_APPEND);
    }
    else
    {
        // 
    }
    
    int fd = 0;
    if(flags & O_RDONLY)
        fd = open(path_name, flags);
    else 
        // 如果是写或追加，可能会创建新文件，所以要设置文件的默认权限
        fd = open(path_name, flags, defaultMode);

    if(fd == -1)
    {
        // 文件打开失败
        char* err = strerror(errno);// 错误信息
        write(2, err, strlen(err));
        return NULL;
    }  
    
    // 文件打开成功
    
    FILE_*fp = (FILE_*)malloc(sizeof(FILE_));
    assert(fp);

    fp->flags = SYNC_LINE;
    fp->fileno = fd;
    fp->capacity = SIZE;
    fp->size = 0;
    memset(fp->buffer, 0, SIZE);

    return fp;
}

void fflush_(FILE_* fp)
{
    // 将数据从缓冲区写入到操作系统中
    if(fp->size > 0)
        write(fp->fileno, fp->buffer, fp->size);
    fsync(fp->fileno);// 将内核中（缓冲区）的数据强制同步到磁盘中。这才是真正的刷新
    fp->size = 0;
}

void fclose_(FILE_* fp)
{
    fflush_(fp);

    close(fp->fileno);
}
void fwrite_(const void* ptr, int num, FILE_* fp)
{
    // 1. 写数据到缓冲区
    // 暂且不考虑缓冲区溢出的问题
    memcpy(fp->buffer+fp->size, ptr, num);
    fp->size += num;
    // 2. 刷新缓冲区
    if(fp->flags & SYNC_NOW)
    {
        write(fp->fileno, fp->buffer, fp->size);
        fp->size = 0;// 清空缓冲区
    }
    else if(fp->flags & SYNC_LINE)
    {
        // 暂不考虑abcd\nefg这种的
        if(fp->buffer[fp->size-1] == '\n')
        {
            write(fp->fileno, fp->buffer, fp->size);
            fp->size = 0;// 清空缓冲区
        }
    }
    else if(fp->flags & SYNC_FULL)
    {
        if(fp->size == fp->capacity)
        {
            // 缓冲区满了
            write(fp->fileno, fp->buffer, fp->size);
            fp->size = 0;// 清空缓冲区
        }
        else
        {
            // 缓冲区没满，不刷新
        }
    }
    else
    {
        // error 
    }
}


